<?php

namespace Pinenut\Form;

use Pinenut\Request;

/**
 * Базовый класс элемента формы
 */

class Element
{
// 	protected $config;

// 	protected $isSlave;

// 	protected $masterValue;

//	protected $partial;

	protected $defaultPathToElements = 'forms.render';
	protected $defaultPathToFilters = 'forms.filter';
	protected $defaultPathToValidators= 'forms.validator';

	/**
	 * Тип элемента, трансформируется в вызов действия для рендеринга элемента
	 * @var string
	 */
	public $type;

	/**
	 * Стиль отображения элемента, для рендеринга используется в качестве 
	 * переключателя вьюх
	 * 
	 * @var string
	 */
	public $style;
	
	
	/**
	 * Имя элемента
	 * @var string
	 */
	public $name;

	/**
	 * Список валидаторов с параметрами
	 * @var array
	 */
	public $validators = [];

	/**
	 * Список фильтров с параметрами
	 * @var array
	 */
	public $filters = [];
	/**
	 * Все остальные параметры, переданые в конфе
	 * @var array
	 */
	public $params = [];

	/**
	 * Ошибки
	 * @var array
	 */
	public $errors = [];
	
	
	/**
	 * Значение
	 * @var mixed
	 */
	public $value;
	
	/**
	 * Имя мастер-элемента
	 * @var string
	 */
	public $master;

	/**
	 * Имя мастер-элемента
	 * @var string
	 */
	public $getMasterValue;
	/**
	 * Значение мастера, если нужно
	 * @var mixed
	 */
	public $masterValue;
	
	/**
	 * Признак того, что при частичной генерации нужно выводить этот элемент
	 * @var unknown
	 */
	public $isRender = false;
	
	public function toArray() {
		return [
			'name' => $this->name,
			'value' => $this->value,
			'master' => $this->master,
			'getMasterValue' => $this->getMasterValue,
			'masterValue' => $this->masterValue,
			'errors' => $this->errors,
			'params' => $this->params,
		];
	}
	
	
	public function __construct($config)
	{

// 		$this->isSlave = empty($config['master']) ? false : true;
		$this->name = isset($config['name'])?$config['name']:null;
		$this->type = isset($config['type'])?$config['type']:null;
		$this->style = isset($config['style'])?$config['style']:null;
		$this->validators = (array)(isset($config['validators'])?$config['validators']:[]);
		$this->filters = (array)(isset($config['filters'])?$config['filters']:[]);
		$this->master = isset($config['master'])?$config['master']:null;
		$this->getMasterValue = isset($config['getMasterValue'])?$config['getMasterValue']:null;
		$this->params = $config; // TODO: вычесть всё что взяли раньше из конфига
		
	}

	public function render($view = null, $json = false)
	{
		if ($json) {
			return \Dispatcher::action(new Request( 
				$this->defaultPathToElements . '.' . $this->type, 
				$this->toArray(), 
				false));
		} else {
			return \Dispatcher::action(new Request(
				$this->defaultPathToElements . '.' . $this->type,
				$this->toArray(),
				(null === $view?$this->style:$view)));
			
		}
	}

	public function getValue()
	{
		return $this->value;
	}

	public function setValue($value)
	{
		$this->value = $value;
//		return $this;
	}

// 	public function setParital($isIt)
// 	{
// 		$this->partial = !!$isIt;
// 	}

// 	public function isPartial()
// 	{
// 		return $this->partial;
// 	}

// 	public function isSlave()
// 	{
// 		return $this->isSlave;
// 	}

// 	public function isMaster()
// 	{
// 		return !$this->isSlave(); /* todo пофиксить */
// 	}

// 	public function getStyle()
// 	{
// 		return isset($this->config['style']) ? $this->config['style'] : null;
// 	}

// 	public function dividerAfter()
// 	{
// 		return isset($this->config['dividerAfter']) ? $this->config['dividerAfter'] : false;
// 	}

// 	public function dividerBefore()
// 	{
// 		return isset($this->config['dividerBefore']) ? $this->config['dividerBefore'] : false;
// 	}

	public function getMaster()
	{
		return $this->master;
	}

	public function setMasterValue($value)
	{
		$this->masterValue = $value;
	}
	
	public function getMasterValue()
	{
		return $this->masterValue;
	}

	public function filter()
	{
		$value = $this->getValue();
		$value = $this->value;
		foreach ($this->filters as $filter => $params) {
			// если простой массив (или строка, которую мы развернули в массив ранее)
			// то нормализуем
			if (is_int($filter)) {
				$filter = $params;
				$params = [];
			}
			// нормализуем параметры
			if (!is_array($params)) {
				$params = (array)$params;
			}
			$params['value'] = $value;
			
			$value = \Dispatcher::action(new Request($this->defaultPathToFilters . '.' . $filter, $params))->content;
		}
		$this->setValue($value);
	}

	public function validate()
	{
		$isValid = true;
		
		foreach ($this->validators as $validator => $params) {
			// если простой массив (или строка, которую мы развернули в массив ранее)
			// то нормализуем
			if (is_int($validator)) {
				// если параметры - массив, значит первый его элемент - имя валидатора, остальное параметры
				if (is_array($params)) {
					$validator = array_shift($params);
				} else {
					$validator = $params;
					$params = [];
				}
			}
			// нормализуем параметры
			if (!is_array($params)) {
				$params = (array)$params;
			}
			$params['value'] = $this->value;
			$params['masterValue'] = $this->getMasterValue();
				
			$error = \Dispatcher::action(new Request($this->defaultPathToValidators . '.' . $validator, $params))->content;
			
			if (!empty($error)) {
				$isValid = false;
				$this->addError($error);
			}
		}

		return $isValid;
	}
	
	public function addError($error) {
		$this->errors[] = $error;
	}
}